﻿using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;

public static class BitmapHelper
{
    /// <summary>
    /// 将byte[]数组转换成彩色图片Bitmap对象
    /// </summary>
    /// <param name="img_bytes">图像的byte数组</param>
    /// <param name="img_width">图像的宽</param>
    /// <param name="img_height">图像的高</param>
    /// <returns>Bitmap对象</returns>
    public static Bitmap Array2Bitmap(byte[] img_bytes, int img_width, int img_height)
    {
        try
        {
            Bitmap m_currBitmap = new Bitmap(img_width, img_height, PixelFormat.Format24bppRgb);
            Rectangle m_rect = new Rectangle(0, 0, img_width, img_height);
            BitmapData m_bitmapData = m_currBitmap.LockBits(m_rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

            // 获取bmpData的内存起始位置  
            IntPtr iptr = m_bitmapData.Scan0;
            int stride = m_bitmapData.Stride;

            // 用Marshal的Copy方法，将刚才得到的内存字节数组复制到BitmapData中  
            Marshal.Copy(img_bytes, 0, iptr, stride * img_height);
            m_currBitmap.UnlockBits(m_bitmapData);

            // 算法到此结束，返回结果  
            return m_currBitmap;
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.Array2Bitmap ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }

    /// <summary>
    /// 图片转存为byte数组
    /// </summary>
    /// <param name="bitmap"></param>
    /// <returns></returns>
    public static byte[] Bitmap2Array(Bitmap bitmap, out int img_stride)
    {
        try
        {
            if (bitmap.PixelFormat != PixelFormat.Format24bppRgb)
            {
                bitmap = ConvertTo24(bitmap);
            }

            // 定义锁定bitmap的rect的指定范围区域
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            // 加锁区域像素
            var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            // 位图的首地址
            var ptr = bitmapData.Scan0;
            // stride：扫描行
            img_stride = bitmapData.Stride;
            int len = bitmapData.Stride * bitmap.Height;
            byte[] img_bytes = new byte[len];
            // 锁定区域的像素值copy到byte数组中
            Marshal.Copy(ptr, img_bytes, 0, len);
            // 解锁
            bitmap.UnlockBits(bitmapData);

            return img_bytes;
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.Bitmap2Array ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }

    /// <summary>
    /// 将图片PixelFormat其它格式转为Format32bppArgb格式
    /// </summary>
    /// <param name="bs"></param>
    /// <param name="filename"></param>
    public static void ToFormat32bppArgb(byte[] bs, string filename)
    {
        try
        {
            MemoryStream ms = new MemoryStream(bs);
            Image imgr = Image.FromStream(ms);
            Bitmap bmp = new Bitmap(imgr.Width, imgr.Height, PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(imgr, new Point(0, 0));
            g.Dispose();
            bmp.Save(filename);
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.ToFormat32bppArgb ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }


    /// <summary>
    /// 将非24bits图片文件转为24bits图片文件
    /// </summary>
    /// <param name="inputFileName"></param>
    /// <param name="outputFileName"></param>
    public static void ConvertTo24(string inputFileName, string outputFileName)
    {
        try
        {
            Bitmap bmpIn = (Bitmap)Bitmap.FromFile(inputFileName);
            Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
            using (Graphics g = Graphics.FromImage(converted))
            {
                g.SmoothingMode = SmoothingMode.HighSpeed;
                g.CompositingQuality = CompositingQuality.HighSpeed;
                g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
                g.InterpolationMode = InterpolationMode.NearestNeighbor;
                // Prevent DPI conversion
                g.PageUnit = GraphicsUnit.Pixel;
                // Draw the image
                g.DrawImageUnscaled(bmpIn, 0, 0);
            }
            converted.Save(outputFileName, ImageFormat.Bmp);
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.ConvertTo24 ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }

    /// <summary>
    /// 将非24bits图片转为24bits图片
    /// </summary>
    /// <param name="bmpIn"></param>
    /// <returns></returns>
    public static Bitmap ConvertTo24(Bitmap bmpIn)
    {
        try
        {
            //PixelFormat.Format32bppArgb;
            Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
            using (Graphics g = Graphics.FromImage(converted))
            {
                g.SmoothingMode = SmoothingMode.HighSpeed;
                g.CompositingQuality = CompositingQuality.HighSpeed;
                g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
                g.InterpolationMode = InterpolationMode.NearestNeighbor;
                // Prevent DPI conversion
                g.PageUnit = GraphicsUnit.Pixel;
                // Draw the image
                g.DrawImageUnscaled(bmpIn, 0, 0);
            }
            return converted;
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.ConvertTo24 ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }

    public static Bitmap LoadImage(string filename)
    {
        try
        {
            // 流模式读取图片；避免线程占用！
            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] buffer = new byte[fs.Length];
                int length = 0;
                int ibyteRead = 0;
                do
                {
                    length = fs.Read(buffer, ibyteRead, buffer.Length - ibyteRead);
                    ibyteRead += length;
                }
                while (length > 0);
                MemoryStream mfs = new MemoryStream(buffer);
                fs.Close();
                fs.Dispose();
                Bitmap result = (Bitmap)Image.FromStream(mfs);
                mfs.Close();
                mfs.Dispose();
                return result;
            }
        }
        catch (Exception ex)
        {
            //MessageBox.Show(ex.Message);
            throw new Exception("BitmapHelper.LoadImage ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }


    private static ImageCodecInfo GetEncoder(ImageFormat format)
    {
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
        foreach (ImageCodecInfo codec in codecs)
        {
            if (codec.FormatID == format.Guid)
            {
                return codec;
            }
        }
        return null;
    }

    public static void SaveImageFile(Bitmap img, string filename)
    {
        try
        {
            FileInfo fx = new FileInfo(filename);
            if (!Directory.Exists(fx.Directory.FullName))
            {
                Directory.CreateDirectory(fx.Directory.FullName);
            }
            switch (fx.Extension.ToLower())
            {
                case ".png":
                    img.Save(filename, ImageFormat.Png);
                    break;
                case ".gif":
                    img.Save(filename, ImageFormat.Gif);
                    break;
                case ".tiff":
                    img.Save(filename, ImageFormat.Tiff);
                    break;
                case ".bmp":
                    img.Save(filename, ImageFormat.Bmp);
                    break;
                case ".jpg":
                case ".jpeg":
                default:
                    ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
                    //创建一个Endoder对象
                    System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
                    // 创建一个EncoderParameters对象.
                    // 一个EncoderParameters对象有一个EncoderParameter数组对象
                    EncoderParameters myEncoderParameters = new EncoderParameters(1);
                    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 100L);
                    myEncoderParameters.Param[0] = myEncoderParameter;
                    img.Save(filename, jgpEncoder, myEncoderParameters);
                    //picResult.Image.Save(saveFileDialog1.FileName, ImageFormat.Jpeg);
                    break;
                    //picResult.Image.Save(saveFileDialog1.FileName + ".jpg", ImageFormat.Jpeg);
                    //break;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.SaveImageFile ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }

    /// <summary>
    /// 图片转为base64编码的文本
    /// </summary>
    /// <param name="bmp"></param>
    /// <returns></returns>
    public static string BitmapToBase64String(Bitmap bmp)
    {
        try
        {
            MemoryStream ms = new MemoryStream();
            // API 提取的缩略图，只能用PNG！！！
            bmp.Save(ms, ImageFormat.Png);
            byte[] arr = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(arr, 0, (int)ms.Length);
            ms.Close();
            string strbaser64 = Convert.ToBase64String(arr);
            return strbaser64;
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.BitmapToBase64String ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }

    /// <summary>
    /// base64编码的文本转为图片
    /// </summary>
    /// <param name="inputStr"></param>
    /// <returns></returns>
    public static Bitmap Base64StringToBitmap(string inputStr)
    {
        try
        {
            byte[] arr = Convert.FromBase64String(inputStr);
            MemoryStream ms = new MemoryStream(arr);
            Bitmap bmp = new Bitmap(ms);
            ms.Close();
            return bmp;
        }
        catch (Exception ex)
        {
            throw new Exception("BitmapHelper.Base64StringToBitmap ERROR:" + ex.Source + " " + ex.TargetSite.Name + " " + ex.Message);
        }
    }
}
